package _Banque;

import java.io.Serializable;

import _Exception.*;

/**
 * Un Compte Epargne est un Compte Bancaire remunere
 * 
 * @authors TVT & Salmeron
 */
public class CompteEpargne extends CompteBancaire implements Serializable
{

	private static final long serialVersionUID = 8720875756950015747L;
	
	private long m_numero;
	private boolean m_cloture;
	private float m_taux=0f;
	private Banque m_banque;
	
	/**
	 * Constructeur par defaut
	 */
	public CompteEpargne(){
		m_numero = 0;
		m_cloture = false;
		m_taux = 1.0f;
	}
	
	/**
	 * Constructeur normal
	 * @param titulaire : le titulaire du compte
	 * @param tauxRemuneration : le taux de remuneration du compte
	 * @throws IPException 
	 */
	public CompteEpargne(final Banque ban, final Titulaire titulaire, final float tauxRemuneration) throws IPException {
		super(ban, titulaire);
		if (tauxRemuneration < 0.f)
			throw new IPException(2, "taux negatif");
		m_numero = ban.numeroRegistreCptE();
		m_taux = tauxRemuneration;
		m_cloture = false;
		m_banque= ban;
	}

	
	/**
	 * pas de clone
	 */
	public Object Clone() throws CloneNotSupportedException
	{
		throw new CloneNotSupportedException();
	}
	
	/**
	 * Retourne le numero du compte
	 */
	public long getNumeroCompte() {
		return m_numero;
	}
	
	/**
	 * Retourne true ssi le compte est cloture
	 */
	public boolean getCloture() {
		return m_cloture;
	}
	
	/**
	 * Retourne le taux d'interet de ce compte
	 */
	public float getTaux() {
		return m_taux;
	}

	/**
	 * Retire des sous sur le compte
	 * (surcharge de la methode de la classe mere 
	 * en prenant en compte le taux sur le retrait < a 200e)
	 */
	protected void sub(float montant) throws IPException, BUException {
		if(montant < 200.0f)
			super.sub(montant * 1.008f);
		else
			super.sub(montant);
	}

	/**
	 * Execute une operation bancaire sur le compte
	 */
	public float executer(OperationBancaire op) throws IPException, BUException
		{
		if (m_cloture)
			throw new BUException("Ne peut pas executer d'operation bancaire sur" +
					" un compte cloture");
		
		if (op == null)
			throw new IPException();
		if(op.getType()!='R' && op.getType()!='V' && op.getType() != 'I')
			throw new IPException("Type d'operation invalide sur ce compte");
		if(op.getIntitule() == null)
			throw new IPException("intitule inconnu");
		if(op.getType() == 'R')
			sub(op.getMontant());
		if(op.getType() == 'V' || op.getType() == 'I')
			add(op.getMontant());
		m_pOperation.put(op.getNumero(), op);
		return getSoldeCompte();
	}
	
	/**
	 * Execute une operation bancaire sur le compte
	 */
	public float executer(String intitule, char type, float montant) throws BUException, IPException {
		return executer(new OperationBancaire(m_banque, type, intitule, montant));
	}
	

	/**
	 * Cloture le compte
	 */
	public float cloturer() throws BUException, IPException {
		if (m_cloture)
			throw new BUException("compte deja cloture");
		float resultat = getSoldeCompte();
		try{
			if (resultat < 200)
				resultat /= 1.008f;
			executer("Fermeture du compte", 'R',  resultat);
		} catch (IPException e) {}
		m_cloture= true;
		return resultat;
	}

	/**
	 * Remunere le compte en fonction de la date donnee en parametre
	 * et du taux d'interet du compte
	 */
	public float remunerer(final String date) throws IPException,  BUException {
		if (!_Banque.validiteDate(date))
			throw new IPException("date invalide");
		
		String today = _Banque.dateCourante();

        if (date.equals(_Banque.debutMoisSuivant(today)) || 
        		date.equals(_Banque.debutAnneeSuivante(today)))
        {
        	int duree= (_Banque.deltaMois(today, date));
        	float taux = (this.getSoldeCompte() * m_taux * duree)/12;
        	return executer("remuneration du compte", 'V', taux);
        }
        // Sinon, on remuneyre pas
        else
        	return getSoldeCompte();

        //return remuneration;

	
	}
	
	/**
	 * equals()
	 */
	public boolean equals(Object op2) {
		if (op2 == null)
			return false;
		if (!super.equals(op2))
			return false;
		return m_numero == ((CompteEpargne)op2).getNumeroCompte() &&
				m_cloture == ((CompteEpargne)op2).getCloture() &&
				m_taux == ((CompteEpargne)op2).getTaux();
	}
	
	/**
	 * toString()
	 */
	public String toString() {
		if (this.equals(new CompteEpargne())) return "---";
		return "\n" + getTitulaireCompte().toString() + "\n" + getNumeroCompte() +" - "+ getSoldeCompte();
	}
	
	
}
